package com.cc.data_explore.gui.tab;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cc.data_explore.logic.data.AnalysisTableData;
import com.cc.data_explore.logic.data.RuleData;
import com.cc.data_explore.logic.data.TableRuleData;
import com.cc.data_explore.logic.mybatis.Db;
import com.cc.data_explore.logic.mybatis.DbHelper;
import com.cc.data_explore.logic.mybatis.mapper.sub.FileDataMapper;
import com.cc.data_explore.logic.mybatis.mapper.sub.FileInfoMapper;
import com.cc.data_explore.logic.mybatis.mapper.sub.TableConfigMapper;
import com.cc.data_explore.logic.mybatis.model.FileData;
import com.cc.data_explore.logic.mybatis.model.FileInfo;
import com.cc.data_explore.logic.mybatis.model.TableConfig;
import com.cc.data_explore.logic.utils.TreeUtils;
import de.saxsys.mvvmfx.ViewModel;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.ObservableMap;
import javafx.scene.control.TreeItem;
import lombok.Getter;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.json.JSONUtil;

import java.util.*;
import java.util.stream.IntStream;

/**
 * @author cc
 * @version 1.0
 * @since 2025/3/30
 */
public class TabViewModel implements ViewModel {

    public static final String COLUMN_CHANGE = "columnChange";
    @Getter
    private final ObservableMap<String, String> columnMap = FXCollections.observableMap(new LinkedHashMap<>());

    private final ObjectProperty<TreeItem<FileInfo>> rootProperty = new SimpleObjectProperty<>();

    private final ObservableList<Map<String, String>> rowList = FXCollections.observableArrayList();

    private final ObservableList<TableRuleData> headers = FXCollections.observableArrayList();

    private final Map<String, RuleData> ruleDataMap = new HashMap<>(64);

    private final IntegerProperty headIndex = new SimpleIntegerProperty(0);

    private Db db;
    private Long currentSheetId;

    public void initialize() {
        System.out.println("TabViewModel初始化完成");
    }

    public void initData(String dbName) {
        createDataSource(dbName);
        buildFileTree();
    }

    private void createDataSource(String dbName) {
        this.db = new Db(dbName, DbHelper.U_MAPPER_PATH);
    }

    public ObjectProperty<TreeItem<FileInfo>> rootProperty() {
        return rootProperty;
    }

    public void buildFileTree() {
        SqlSessionFactory sqlSessionFactory = this.db.getSqlSessionFactory();
        if (sqlSessionFactory == null) {
            return;
        }
        try (SqlSession sqlSession = sqlSessionFactory.openSession(true)) {
            FileInfoMapper mapper = sqlSession.getMapper(FileInfoMapper.class);
            List<FileInfo> fileInfoList = mapper.selectList(Wrappers.emptyWrapper());
            if (CollUtil.isEmpty(fileInfoList)) {
                return;
            }
            List<FileInfo> build = TreeUtils.build(fileInfoList, -1L);
            TreeItem<FileInfo> root = buildTreeItem(build.get(0));
            rootProperty.set(root);
        }
    }

    // 递归方法：将 Department 转换为 TreeItem
    private TreeItem<FileInfo> buildTreeItem(FileInfo fileInfo) {
        TreeItem<FileInfo> t = new TreeItem<>(fileInfo);
        if (CollUtil.isEmpty(fileInfo.getChildren())) {
            return t;
        }
        for (FileInfo info : fileInfo.getChildren()) {
            // 递归调用
            t.getChildren().add(buildTreeItem(info));
        }
        return t;
    }

    public void loadData() {
        SqlSessionFactory sqlSessionFactory = this.db.getSqlSessionFactory();
        try (SqlSession sqlSession = sqlSessionFactory.openSession(true)) {
            TableConfig tc = sqlSession.getMapper(TableConfigMapper.class).selectOne(Wrappers.emptyWrapper());
            if (tc != null) {
                String headList = tc.getHeadList();
                List<AnalysisTableData> analysisTableDataList = JSONUtil.toList(headList, AnalysisTableData.class);
                List<TableRuleData> list = IntStream.range(0, analysisTableDataList.size()).mapToObj(m -> {
                    AnalysisTableData analysisTableData = analysisTableDataList.get(m);
                    String tableFieldZh = analysisTableData.getTableFieldZh();
                    TableRuleData trd = new TableRuleData();
                    trd.setTargetIndex(m);
                    trd.setTargetName(tableFieldZh);
                    return trd;
                }).toList();
                headers.setAll(list);
            }
            FileDataMapper mapper = sqlSession.getMapper(FileDataMapper.class);
            List<FileData> fileData = mapper.selectList(Wrappers.<FileData>lambdaQuery().eq(FileData::getSheetId, currentSheetId));
            if (columnMap.isEmpty()) {
                FileData fileData1 = fileData.get(0);
                String colContent = fileData1.getDataContent();
                Map<String, String> colMap = JSONUtil.parse(colContent).toBean(Map.class);
                columnMap.putAll(colMap);
                publish(COLUMN_CHANGE);
                // setTableColumn(colMap);
            }
            for (FileData fileDatum : fileData) {
                String dataContent = fileDatum.getDataContent();
                Map<String, String> parse = JSONUtil.parse(dataContent).toBean(Map.class);
                rowList.add(parse);
            }
        } catch (Exception e) {
            e.printStackTrace();
            currentSheetId = null;
        }
    }

    public Boolean checkIsSelected(Long sheetId) {
        if (currentSheetId == null) {
            currentSheetId = sheetId;
            return null;
        }
        return sheetId.equals(currentSheetId);
    }

    public boolean checkPrimaryTable() {
        SqlSessionFactory sqlSessionFactory = this.db.getSqlSessionFactory();
        try (SqlSession sqlSession = sqlSessionFactory.openSession(true)) {
            TableConfigMapper mapper = sqlSession.getMapper(TableConfigMapper.class);
            return mapper.exists(Wrappers.emptyWrapper());
        }
    }

    public ObservableList<Map<String, String>> rowList() {
        return rowList;
    }

    public ObservableList<TableRuleData> headers() {
        return headers;
    }

    public void saveCleanData() {
        List<Map<String, String>> cleanDataList = new LinkedList<>();
        for (TableRuleData rule : headers) {
            int sourceIndex = rule.getSourceIndex();
            String targetNameEn = rule.getTargetNameEn();
            if (sourceIndex == -1) {
                continue;
            }
            for (Map<String, String> map : rowList) {
                Map<String, String> cleanDataMap = new HashMap<>(map.size());
                String data = map.get("" + sourceIndex);
                if (StrUtil.isEmpty(data)) {
                    continue;
                }
                cleanDataMap.put(targetNameEn, data);
                cleanDataList.add(cleanDataMap);
            }
            if (rowList.size() > 10_000) {
                //查询10000行之后的数据进行规则处理
            }
        }
    }

    public int getHeadIndex() {
        return headIndex.get();
    }

    public IntegerProperty headIndexProperty() {
        return headIndex;
    }
}
